﻿using Framework.Domain.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
using Framework.Infrastructure;
using EntityFramework.Extensions;
using System.Data.Entity.Migrations;
using Framework.Repository.Extensions;

namespace Framework.Repository
{
    public class BaseRepository<T> where T : class
    {
        protected FrameworkContext Context = new FrameworkContext();

        /// <summary>
        /// 查询单个（根据任何字段）
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public T FindSingle(Expression<Func<T, bool>> exp = null)
        {
            return Context.Set<T>().AsNoTracking().FirstOrDefault(exp);
        }

        /// <summary>
        /// 查询单个（根据主键）
        /// </summary>
        /// <param name="keys"></param>
        /// <returns></returns>
        public T FindByKey(params object[] keys)
        {
            return Context.Set<T>().Find(keys);
        }

        /// <summary>
        /// 查询集合
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IQueryable<T> FindList(Expression<Func<T, bool>> exp = null)
        {
            return Filter(exp);
        }

        /// <summary>
        /// 查询分页（单表）
        /// </summary>
        /// <param name="pageIndex">页码，默认：1</param>
        /// <param name="pageSize">每页条数，默认：10</param>
        /// <param name="orderBy">排序方式，默认：Id descending，支持多列排序</param>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IQueryable<T> FindPaged(int pageIndex = 1, int pageSize = 12, string orderBy = "", Expression<Func<T, bool>> exp = null)
        {
            if (pageIndex < 1) pageIndex = 1;
            if (pageSize < 1) pageSize = 12;
            if (string.IsNullOrEmpty(orderBy)) orderBy = "Id descending";

            return Filter(exp).OrderBy(orderBy).Skip(pageSize * (pageIndex - 1)).Take(pageSize);
        }

        /// <summary>
        /// 查询分页（万能查询）
        /// </summary>
        /// <param name="condtion">万能条件</param>
        /// <param name="includeTable">关联表，英文逗号分隔</param>
        /// <returns></returns>
        public Paged<T> FindPaged(QueryCondition condtion = null, string includeTable = null)
        {
            if (condtion.PageIndex < 1) condtion.PageIndex = 1;
            if (condtion.PageSize < 1) condtion.PageSize = 12;

            var query = Context.Set<T>().AsQueryable();

            //加载关联表
            if (!string.IsNullOrWhiteSpace(includeTable))
            {
                var tableArr = includeTable.Split(',');
                foreach (var table in tableArr)
                {
                    query = query.Include(table);
                }
            }

            if (condtion.FilterList != null && condtion.FilterList.Count > 0)
            {
                query = query.Where(condtion);
            }
            int totalCount = query.Count();

            if (string.IsNullOrWhiteSpace(condtion.SortBy) && string.IsNullOrWhiteSpace(condtion.ThenSortBy))//必须有排序列，否则报错
            {
                query = query.OrderBy("Id", false);
            }
            else
            {
                if (!string.IsNullOrWhiteSpace(condtion.SortBy))
                {
                    query = query.OrderBy(condtion.SortBy, condtion.SortOrder);
                }
                if (!string.IsNullOrWhiteSpace(condtion.ThenSortBy))
                {
                    query = query.ThenBy(condtion.ThenSortBy, condtion.ThenSortOrder);
                }
            }
            query = query.Skip((condtion.PageIndex - 1) * condtion.PageSize).Take(condtion.PageSize);
            return new Paged<T>(totalCount, condtion.PageSize, condtion.PageIndex, (IEnumerable<T>)query);
        }

        /// <summary>
        /// 查询（万能查询）不分页
        /// 注：不分页也只查询前1000条记录，防止超大表占满内存
        /// </summary>
        /// <param name="condtion">万能条件</param>
        /// <param name="includeTable">关联表，英文逗号分隔</param>
        /// <returns></returns>
        public List<T> FindNoPaged(QueryCondition condtion = null, string includeTable = null)
        {
            var query = Context.Set<T>().AsQueryable();

            //加载关联表
            if (!string.IsNullOrWhiteSpace(includeTable))
            {
                var tableArr = includeTable.Split(',');
                foreach (var table in tableArr)
                {
                    query = query.Include(table);
                }
            }

            if (condtion != null)
            {
                query = query.Where(condtion);
            }
            if (!string.IsNullOrEmpty(condtion.SortBy))
            {
                query = query.OrderBy(condtion.SortBy, condtion.SortOrder);
            }
            return query.Take(1000).ToList();
        }

        /// <summary>
        /// 是否存在
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public bool IsExist(Expression<Func<T, bool>> exp)
        {
            return Context.Set<T>().Any(exp);
        }

        /// <summary>
        /// 查询个数
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public int GetCount(Expression<Func<T, bool>> exp = null)
        {
            return Filter(exp).Count();
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="entity"></param>
        public int Add(T entity)
        {
            Context.Set<T>().Add(entity);
            return Context.SaveChanges();
        }

        /// <summary>
        /// 批量添加
        /// </summary>
        /// <param name="entities"></param>
        public int BatchAdd(T[] entities)
        {
            Context.Set<T>().AddRange(entities);
            return Context.SaveChanges();
        }

        /// <summary>
        /// 更新所有字段（主键外所有字段）
        /// </summary>
        /// <param name="entity"></param>
        public int Update(T entity)
        {
            var entry = Context.Entry(entity);
            entry.State = EntityState.Modified;
            return Context.SaveChanges();
        }

        ///// <summary>
        ///// 更新整个实体
        ///// </summary>
        ///// <param name="identityExp"></param>
        ///// <param name="entity"></param>
        //public int Update(Expression<Func<T, object>> identityExp, T entity)
        //{
        //    Context.Set<T>().AddOrUpdate(identityExp, entity);
        //    return Context.SaveChanges();
        //}

        /// <summary>
        /// 更新部分字段
        /// </summary>
        /// 如：Update(u => u.Id == 1,u => new User{ Name = "wangjie" });
        /// <param name="where">更新条件</param>
        /// <param name="entity">更新后的实体</param>
        public int Update(Expression<Func<T, bool>> where, Expression<Func<T, T>> entity)
        {
            return Context.Set<T>().Where(where).Update(entity);
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="entity"></param>
        public int Delete(T entity)
        {
            Context.Set<T>().Remove(entity);
            return Context.SaveChanges();
        }

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="exp"></param>
        public int Delete(Expression<Func<T, bool>> exp)
        {
            return Context.Set<T>().Where(exp).Delete();
        }

        #region 私有方法
        private IQueryable<T> Filter(Expression<Func<T, bool>> exp)
        {
            var dbSet = Context.Set<T>().AsQueryable();
            if (exp != null)
                dbSet = dbSet.Where(exp);
            return dbSet;
        }
        #endregion

    }
}
